export function isFunction(val) {
  return typeof val == 'function'
}

export function isObject(val) {
  return typeof val == 'object' && val !== null
}

export let isArray = Array.isArray
let callbacks = []
let waiting = false
function flushCallbacks() {
  callbacks.forEach((fn) => fn()) // 按顺序清空callback
  callbacks = [];
  waiting = false
}
export function nextTick(fn) {
  callbacks.push(fn)
  if (!waiting) {
    Promise.resolve().then(flushCallbacks)
    waiting = true
  }
}

let strats = {}
// 珠峰只给生命周期钩子定义在了strats，源码中将data，props，watch，provide等属性都定义了不同的处理方法，在这些定义的之外，如果父子都有，去子的值
let lifeCycle = [
  'breforCreate',
  'created',
  'beforeMount',
  'mounted'
];
lifeCycle.forEach(hook => {
  strats[hook] = function (parentVal, childVal) {
    if (childVal) {
      if (parentVal) { // 如果父亲有值则肯定已经为数组了
        return parentVal.concat(childVal)
      } else { // 儿子有值父亲没值
        if (Array.isArray(childVal)) {
          return childVal
        } else {
          return [childVal]
        }
      }
    } else {
      return parentVal
    }
  }
})


/* 
parentVal 全局的组件
childVal  局部的组件
*/
strats.components = function (parentVal, childVal) {
  let res = Object.create(parentVal); // 创建对象res__proto__ = parentVal
  for (let k in childVal) {
    res[k] = childVal[k]
  } 
  return res
}
export function mergeOptions(parentVal, childVal) {
  const options = {}
  for (let key in parentVal) {
    mergeFiled(key)
  }
  for (let key in childVal) {
    if (!parentVal.hasOwnProperty(key)) {
      mergeFiled(key)
    }
  }
  function mergeFiled(key) {
    // starts的key 对merge时的特殊key分别做处理，如果key为生命周期会处理成数组[fn1,fn2]，如果是components属性
    let start = strats[key];
    if (start) {
      options[key] = start(parentVal[key], childVal[key])
    } else {
      options[key] = childVal[key] || parentVal[key] // 如果新传入的有该属性，先直接覆盖parent中的
    }
  }
  return options;
}